package algocity.vista;

import algocity.modelo.juego.Calesita;
import algocity.modelo.juego.Cambiador;
import algocity.modelo.juego.Jugador;
import algocity.modelo.mapa.Hectarea;

import javax.swing.*;
import java.awt.*;


public class VistaMapa
    extends JPanel
    implements MapaVista, Scrollable {

    private final Jugador jugador;
    private final FlowLayout layout;
    private double ladoHectarea;

    // Coordenadas máximas y mínimas del mapa (absolutas)
    private double xMax;
    private double yMax;
    private double xMin;
    private double yMin;
    private Cambiador<DibujadorMapa> calesita;
    private DibujadorMapa dibujador;

    public void cambiarDibujador() {
        this.calesita.cambiar();
        this.dibujador = calesita.item();
    }

    public VistaMapa(Jugador jugador) {
        this.jugador = jugador;

        this.calesita = new Calesita<DibujadorMapa>();
        calesita.agregar( new DibujadorHectarea(this));
        calesita.agregar( new DibujadorConexiones(this));

        dibujador = calesita.item();

        inicializarPosiciones();

        setBorder(BorderFactory.createLineBorder(Color.black));
        layout = new FlowLayout(FlowLayout.CENTER);
        setLayout(layout);
        // Es necesario colocar las dimensiones
        setSize(VistaParametros.ANCHO_FICTICIO_MAPA, VistaParametros.ALTO_FICTICIO_MAPA);
    }

    private void inicializarPosiciones() {
        this.xMax = Integer.MIN_VALUE;
        this.yMax = Integer.MIN_VALUE;
        this.xMin = Integer.MAX_VALUE;
        this.yMin = Integer.MAX_VALUE;
        this.ladoHectarea = VistaParametros.ANCHO_FICTICIO_MAPA / VistaParametros.HECTAREAS_POR_PANTALLA;
    }

    public double getxMax() {
        return xMax;
    }

    public double getyMax() {
        return yMax;
    }

    @Override
    public boolean estaEnElMapa(double xEnPantalla, double yEnPantalla) {
        return getxMin() < xEnPantalla && xEnPantalla < getxMax() &&
                getyMin() < yEnPantalla && yEnPantalla < getyMax();

    }

    public double getxMin() {
        return xMin;
    }

    public double getyMin() {
        return yMin;
    }

    /**
     * Recolecta qué posición de hectárea se está dibujando
     * @param xMin posición x relativa a la primer hectárea
     * @param yMin posición y relativa a la primer hectárea
     */
    public void colectarLimite(double xMin, double yMin) {
        Point point = new Point();
        SwingUtilities.convertPointToScreen(point,this);

        double xMinEnPantalla = point.getX() + xMin;
        double yMinEnPantalla = point.getY() + yMin;
        this.xMax = Math.max( xMinEnPantalla + ladoHectarea, this.xMax);
        this.yMax = Math.max( yMinEnPantalla + ladoHectarea, this.yMax);
        this.xMin = Math.min( xMinEnPantalla, this.xMin);
        this.yMin = Math.min( yMinEnPantalla, this.yMin);
    }

    @Override
    public Hectarea getHectarea(Point locationOnScreen) {
        Point thisLocation = getLocationOnScreen();
        int x = (int) ( ( locationOnScreen.getX() - thisLocation.getX() ) / ladoHectarea );
        int y = (int) ( ( locationOnScreen.getY() - thisLocation.getY() ) / ladoHectarea );;
        return jugador.getMapa().iterator(x,y).elementoActual();
    }

    public Dimension getPreferredSize(){
        algocity.modelo.mapa.Dimension dimensiones = jugador.getMapa().getDimensiones();
        return new Dimension( (int) (dimensiones.getX() * ladoHectarea), (int) (dimensiones.getY() * ladoHectarea) );
    }



    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        inicializarPosiciones();

        dibujador.setContextoGrafico(g2);
        jugador.getMapa().scan(dibujador);
        dibujador.postScan();
    }

    public double getLadoHectarea() {
        return ladoHectarea;
    }

    @Override
    public void actualizar(Hectarea hectarea) {
        actualizar();
    }

    @Override
    public void limpiar() {

    }

    @Override
    public void actualizar() {
        revalidate();
        repaint();
    }


    @Override
    public Dimension getPreferredScrollableViewportSize() {
        return new Dimension((int)( VistaParametros.HECTAREAS_POR_PANTALLA * ladoHectarea), (int) (VistaParametros.HECTAREAS_POR_PANTALLA * ladoHectarea) );
    }

    @Override
    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
        return VistaParametros.HECTAREAS_DE_AVANCE_EN_INCREMENTO_UNITARIO * VistaParametros.ANCHO_FICTICIO_MAPA / VistaParametros.HECTAREAS_POR_PANTALLA;
    }

    @Override
    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
        return VistaParametros.HECTAREAS_DE_AVANCE_EN_INCREMENTO_POR_BLOQUE * VistaParametros.ANCHO_FICTICIO_MAPA / VistaParametros.HECTAREAS_POR_PANTALLA;
    }

    @Override
    public boolean getScrollableTracksViewportWidth() {
        return false;
    }

    @Override
    public boolean getScrollableTracksViewportHeight() {
        return false;
    }

}
